package com.dalei.vds.environment;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;

import com.dalei.vds.graphics.ImageUtils;
import com.dalei.vds.io.Dirctory;
import com.dalei.vds.settings.DeviceSettings;
import com.dalei.vds.settings.ImageSettings;
import com.dalei.vdserver.shared.model.DetectionResult;
import com.dalei.vdserver.shared.model.VehicleInformation;
import com.google.gson.Gson;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.SparseArray;

public class CurrentTask {

	private static final int[] IMAGE_KEYS = new int[] { 5, 6, 7, 8, 9, 10, 11,
			12 };

	private static final String SUFFIX_JSON = ".json";

	private static final String SUFFIX_CRC32 = ".crc32";

	private static int fid = -1;

	private static VehicleInformation vehicleInformation;

	private static boolean isTaskLocked = false;

	private static List<Integer> invalidItems = null;

	private static SparseArray<File> images = null;

	private static int odometerReading = -1;

	private static String notes = null;

	private static Date timeStamp = null;

	public static int getFid() {
		return fid;
	}

	public static void setFid(int fid) {
		CurrentTask.fid = fid;
	}

	public static VehicleInformation getVehicleInformation() {
		return vehicleInformation;
	}

	public static void setVehicleInformation(
			VehicleInformation vehicleInformation) {
		CurrentTask.vehicleInformation = vehicleInformation;
	}

	public static boolean isTaskLocked() {
		return isTaskLocked;
	}

	public static void setTaskLocked(boolean isTaskLocked) {
		CurrentTask.isTaskLocked = isTaskLocked;
	}

	public static List<Integer> getInvalidItems() {
		if (invalidItems == null) {
			invalidItems = new ArrayList<Integer>();
		}
		return invalidItems;
	}

	public static void setInvalidItems(List<Integer> invalidItems) {
		CurrentTask.invalidItems = invalidItems;
	}

	public static SparseArray<File> getImages() {
		if (images == null) {
			images = new SparseArray<File>();
		}
		return images;
	}

	public static void setImages(SparseArray<File> images) {
		CurrentTask.images = images;
	}

	public static int getOdometerReading() {
		return odometerReading;
	}

	public static void setOdometerReading(int odometerReading) {
		CurrentTask.odometerReading = odometerReading;
	}

	public static String getNotes() {
		return notes;
	}

	public static void setNotes(String notes) {
		CurrentTask.notes = notes;
	}

	public static Date getTimeStamp() {
		return timeStamp;
	}

	public static void setTimeStamp(Date timeStamp) {
		CurrentTask.timeStamp = timeStamp;
	}

	@SuppressLint("UseSparseArrays")
	public static DetectionResult getDetectionResult(Context context)
			throws IOException {
		DetectionResult result = null;
		File temp = Dirctory.tempDirctory();
		if (temp != null) {
			File jsonFile = new File(temp, fid + SUFFIX_JSON);
			File crc32File = new File(temp, fid + SUFFIX_CRC32);
			if (jsonFile.exists() && crc32File.exists()) {
				long crc32 = 0;
				InputStream in = new FileInputStream(crc32File);
				if (in != null) {
					DataInputStream dis = new DataInputStream(in);
					if (dis != null) {
						crc32 = dis.readLong();
						dis.close();
					}
					in.close();
				}
				if (FileUtils.checksumCRC32(jsonFile) == crc32) {
					String json = FileUtils.readFileToString(jsonFile);
					Gson gson = new Gson();
					result = gson.fromJson(json, DetectionResult.class);
					return result;
				}
			}
			DeviceSettings deviceSettings = new DeviceSettings(context);
			int deviceId = deviceSettings.getDeviceId();
			
			Map<Integer, byte[]> map = null;
			File cache = Dirctory.cacheDirctory();
			if (cache != null) {
				ImageSettings imageSettings = new ImageSettings(context);
				float scale = (float) imageSettings.getScale();
				map = new HashMap<Integer, byte[]>();
				for (int key : IMAGE_KEYS) {
					File source = getImages().get(key);
					if (source != null) {
						File target = new File(cache, source.getName());
						if (ImageUtils.compressImage(source, target, scale,
								Bitmap.CompressFormat.JPEG)) {
							map.put(key, FileUtils.readFileToByteArray(target));
						} else {
							return null;
						}
					}
				}
				Dirctory.clearCacheDirctory();
			} else {
				return null;
			}
			
			Date timestamp = new Date();
			
			result = new DetectionResult();
			result.setFid(fid);
			result.setDeviceId(deviceId);
			result.setUserId(SystemStatus.getUserId());
			result.setOdometerReading(odometerReading);
			result.setInvalidItems(getInvalidItems());
			result.setImages(map);
			result.setTimeStamp(timestamp);
			
			Gson gson = new Gson();
			String json = gson.toJson(result, DetectionResult.class);
			FileUtils.writeStringToFile(jsonFile, json);
			long crc32 = FileUtils.checksumCRC32(jsonFile);
			OutputStream out = new FileOutputStream(crc32File);
			DataOutputStream dos = new DataOutputStream(out);
			dos.writeLong(crc32);
			dos.close();
			out.close();
			
			return result;
		} else {
			return null;
		}
	}
	
	@SuppressLint("UseSparseArrays")
	public static String getDetectionResultInJson(Context context)
			throws IOException {
		DetectionResult result = null;
		File temp = Dirctory.tempDirctory();
		if (temp != null) {
			File jsonFile = new File(temp, fid + SUFFIX_JSON);
			File crc32File = new File(temp, fid + SUFFIX_CRC32);
			if (jsonFile.exists() && crc32File.exists()) {
				long crc32 = 0;
				InputStream in = new FileInputStream(crc32File);
				if (in != null) {
					DataInputStream dis = new DataInputStream(in);
					if (dis != null) {
						crc32 = dis.readLong();
						dis.close();
					}
					in.close();
				}
				if (FileUtils.checksumCRC32(jsonFile) == crc32) {
					String json = FileUtils.readFileToString(jsonFile);
					return json;
				}
			}
			DeviceSettings deviceSettings = new DeviceSettings(context);
			int deviceId = deviceSettings.getDeviceId();
			
			Map<Integer, byte[]> map = null;
			File cache = Dirctory.cacheDirctory();
			if (cache != null) {
				ImageSettings imageSettings = new ImageSettings(context);
				float scale = (float) imageSettings.getScale();
				map = new HashMap<Integer, byte[]>();
				for (int key : IMAGE_KEYS) {
					File source = getImages().get(key);
					if (source != null) {
						File target = new File(cache, source.getName());
						if (ImageUtils.compressImage(source, target, scale,
								Bitmap.CompressFormat.JPEG)) {
							map.put(key, FileUtils.readFileToByteArray(target));
						} else {
							return null;
						}
					}
				}
				Dirctory.clearCacheDirctory();
			} else {
				return null;
			}
			
			Date timestamp = new Date();
			
			result = new DetectionResult();
			result.setFid(fid);
			result.setDeviceId(deviceId);
			result.setUserId(SystemStatus.getUserId());
			result.setOdometerReading(odometerReading);
			result.setInvalidItems(getInvalidItems());
			result.setImages(map);
			result.setTimeStamp(timestamp);
			
			Gson gson = new Gson();
			String json = gson.toJson(result, DetectionResult.class);
			FileUtils.writeStringToFile(jsonFile, json);
			long crc32 = FileUtils.checksumCRC32(jsonFile);
			OutputStream out = new FileOutputStream(crc32File);
			DataOutputStream dos = new DataOutputStream(out);
			dos.writeLong(crc32);
			dos.close();
			out.close();
			
			return json;
		} else {
			return null;
		}
	}
}
